#include "tcpserver.h"

TcpServer::TcpServer(QObject *parent) : QObject(parent)
{
    //注册传递信息
    qRegisterMetaType<OneTaregtBullet>("OneTaregtBullet");

    //初始化配置文件
    checkTools.initTargetConfig();

//    start();

    startTimer();
    //跨线程调用使用信号和槽
    connect(this,&TcpServer::mySignalSendInfo,this,&TcpServer::slotSendInfo);
}

TcpServer::~TcpServer()
{
    delete tcpServer;
    tcpServer=nullptr;

    delete readbyteProcess;
    readbyteProcess=nullptr;

    delete api;
    api=nullptr;
}

void TcpServer::start()
{
    tcpServer=new QTcpServer();

//    trueapi = new TrueApi();
    api = new TrueApi();

    connect(tcpServer,&QTcpServer::newConnection,this,&TcpServer::onNewconnect);

    readbyteProcess=new ReadbyteProcess();
//    connect(readbyteProcess,SIGNAL(mySignalTargetInfo(const OneTargetBullet&)),this,SLOT(slotsTargetInfo(const OneTargetBullet&)));
    connect(readbyteProcess,&ReadbyteProcess::mySignalTargetInfo,this,&TcpServer::slotsTargetInfo);
//    connect(readbyteProcess,SIGNAL(mySignalRelayStringWriteBack(QString)),this,SLOT(RelayStringWriteBack(QString)));
    connect(readbyteProcess,&ReadbyteProcess::mySignalRelayStringWriteBack,this,&TcpServer::RelayStringWriteBack);

    if(!tcpServer->listen(QHostAddress::Any,ServerListenPort))
    {

        qWarning()<<"connect Serverfailed!";
    }
    else
    {
        qDebug()<<QHostAddress::AnyIPv4<<"  78910  "<<ServerListenPort;
        qInfo()<<"connect Serverstart!";
    }
    qDebug()<<this->thread()<<"    tcpserver  56";
}


void TcpServer::onNewconnect()
{
    QTcpSocket *socket=tcpServer->nextPendingConnection();
    QString clientIP=socket->peerAddress().toString();

    clientSocketMap.insert(clientIP,socket);

    connect(socket,&QTcpSocket::readyRead,this,&TcpServer::onreadReady);
    connect(socket,&QTcpSocket::disconnected,this,&TcpServer::ondisconnect);

    qInfo() << QString("等待连接中...., server addr:  %1  :   %2").arg(clientIP).arg(socket->peerPort());
}

void TcpServer::ondisconnect()
{
    //接受传递信号的发送者，处理数据
    QObject *obj=sender();
    QTcpSocket *socket=qobject_cast<QTcpSocket *>(obj);

    QString clientIP=socket->peerAddress().toString();

    clientSocketMap.remove(clientIP);
}

void TcpServer::onreadReady()
{
    //接受传递信号的发送者，处理数据
    QObject *obj=sender();
    QTcpSocket *socket=qobject_cast<QTcpSocket *>(obj);

    QString clientIP=socket->peerAddress().toString();
    if(clientIP==RelayIp || clientIP==isRelayTest)
    {
        qDebug()<<"中继信息接收...";
        while(socket->bytesAvailable())
        {
            // 读取一部分可用数据
            QByteArray data = socket->read(1);

            // 定义一个uint16_t类型的 变量
            uint16_t value;

            // 将QByteArray的数据拷贝到value中
            memcpy(&value, data.constData(), sizeof(value));

            // 将读取到的数据添加到缓存区中
            readbyteProcess->stateProcess(value);
        }
    }else{
        //与界面进行交互
        while(socket->bytesAvailable() > 0){
            QByteArray recvBuffer = socket->readAll();

            qDebug() << "recvBuffer : " << recvBuffer;
            if(recvBuffer.size() > 0){
                QByteArray temp;
                for(int i = 0;i < recvBuffer.size();i++){
                    if(recvBuffer.at(i) == '\n'){
                        //界面控制指令
                        UiControl(temp);
                        qDebug() << "Server Recv : " << temp;
                        temp.clear();
                      }else{
                        temp.append(recvBuffer.at(i));
                      }
                  }
              }
          }
      }
}


QByteArray TcpServer::ToString(const QByteArray& string)
{
      QString byte;
      for(int i=0;i<string.size();i+=2)
      {
//          QByteArray arr=QByteArray::fromHex(string.mid(i,2));
          QString str=string.mid(i,2).toHex();
          byte+=str;
      }

      return byte.toLatin1();
}



void TcpServer::RelayStringWriteBack(QString msg)
{
  QByteArray resp = QByteArray::fromHex(msg.toLatin1());
  if (resp.isEmpty())
    {
      qDebug() << QString("回发信息解析出错 ==> " + msg);
      return;
    }

  // 先判断 套接字是否可用 进行与中继连接的写入操作
  //通过广播发送

  QTcpSocket *socket = clientSocketMap[RelayIp];
  if(socket && socket->state() == QAbstractSocket::ConnectedState)
    {
      socket->write(resp);
      socket->flush();
      qDebug() << QString("成功回复中继 ==> msg: " + msg);
    }
}

void TcpServer::RelayInfoToUi(const QByteArray& msg)
{
  //向请求客户端发送
  for(auto it = clientSocketMap.begin();it != clientSocketMap.end();it++)
    {
      QTcpSocket *socket = clientSocketMap[it.key()];

      if(socket && socket->state() == QAbstractSocket::ConnectedState)
        {
          socket->write(msg);
          socket->flush();
          qDebug() << QString("成功回复前端 ==> msg: " +msg);
        }
    }
}

void TcpServer::UiControl(QByteArray recvBuffer)
{

  QString recvStr = QString::fromUtf8(recvBuffer);

  //构建JSON对象
  QJsonDocument jsonDocument = QJsonDocument::fromJson(recvStr.toLocal8Bit().data());

  if(jsonDocument.isNull())
    {
      qDebug() <<"jsonDocument is null";
      return ;
    }

  QJsonObject json = jsonDocument.object();

  //  Json转QMap
  QVariantMap map = json.toVariantMap();

  int code = map["code"].toInt();
  int addr,old_addr,new_addr,x,y,groupNumber,distance;
  QString time;
  QMap<QString, QVariant> dataMap = map["data"].toMap();
  QMap<QString, QVariant> msgMap = map["msg"].toMap();
  switch(code){
        //RewriteTargetId
    case 10000:
      old_addr = dataMap["old_addr"].toInt();
      new_addr = dataMap["new_addr"].toInt();
      RewriteTargetIdHandle(old_addr,new_addr);
      break;
      //ClearTarget
    case 10001:
      addr = dataMap["addr"].toInt();
      toClearTarget(addr);
      break;
      //OpenCalibrationTargetById
    case 10002:
      addr = dataMap["addr"].toInt();
      OpenCalibrationTarget(addr);
      break;
      //CloseCalibrationTargetById
    case 10003:
      addr = dataMap["addr"].toInt();
      CloseCalibrationTarget(addr);
      break;
      //OpenInfoEntry
    case 10004:
      break;
      //CloseInfoEntry
    case 10005:
      break;
      //UserGrouping
    case 10006:
      CurGroupNumber = dataMap["group_number"].toInt();
//      readbyteProcess->getTargetGroupnumber(CurGroupNumber);
      break;
      //BindInfo
    case 10007:
      break;
      //ChangeSystemId
    case 10008:
      SystemID = dataMap["SystemID"].toInt();
      initConfig.setIntValue("DateNumber","SystemID",SystemID);
      break;
      //upORdown
    case 10010:
      distance = dataMap["up_down"].toInt();
      qDebug()<<"distance:*********************"<<distance;
      break;
      //GetShowInfo
    case 20002:
      //用一个全局容器接收查找到的数据，给sqlitethread
      addr = dataMap["addr"].toInt();
      groupNumber = dataMap["group_number"].toInt();
      time = msgMap["date"].toString();
      readbyteProcess->GetSearchDate(groupNumber,addr,time);
      emit mySignalSendInfo(api->pushSearchDateApi());
      break;

      //GetVoltage
    case 20003:
      emit mySignalSendInfo(api->pushTargetVoltageInfoApi());
      break;
      //TwoCheck
    case 10009:
      addr = dataMap["addr"].toInt();
      x = dataMap["x"].toInt();
      y = dataMap["y"].toInt();
      ManualCalibration(addr,x,y);
      break;
      //GetTargetName
    case 20004:
      break;
      //currentData
    case 20007:
      time = msgMap["date"].toString();
      initConfig.setStringValue("searchDate","searchDateDate",time);
      break;
    case 20008:
      addr = dataMap["addr"].toInt();
      groupNumber = dataMap["group_number"].toInt();
      initConfig.setIntValue("searchDate","searchDateAddr",addr);
      initConfig.setIntValue("searchDate","searchDateGroupNumber",groupNumber);
      break;
    default:
      break;
    }
}

void TcpServer::startTimer()
{
    stateTimer.setInterval(StateTime);
    connect(&stateTimer,&QTimer::timeout,[=](){
        //请求状态5s
        emit mySignalSendInfo(api->pushTargetStateInfoApi());
    });
    stateTimer.start();

    voltageTimer.setInterval(VoltageTime);
    connect(&voltageTimer,&QTimer::timeout,[=](){
        //请求电量60s
        emit mySignalSendInfo(api->pushTargetVoltageInfoApi());
    });
    voltageTimer.start();

}

void TcpServer::slotSendInfo(const QByteArray& info)
{
  RelayInfoToUi(info);
}

void TcpServer::slotsTargetInfo(const OneTaregtBullet& oneTaregtBullet)
{
  emit mySignalSendInfo(api->currentTargetBullet(oneTaregtBullet));
}


void TcpServer::RewriteTargetIdHandle(int oldID, int newID)
{
  qDebug() << QString("重写地址  %1  ==》 %2").arg(oldID).arg(newID);
  QString oldIDString = QString::number(oldID, 16).rightJustified(2, '0');
  QString newIDString = QString::number(newID, 16).rightJustified(2, '0');
  unsigned int systemId = SystemID;
  QString systemIDString = QString::number(systemId, 16).rightJustified(4, '0');
  QVector<uint16_t> d = {0, uint16_t(systemId >> 8), uint16_t(systemId & 0xFF), 0x90, uint16_t(newID),
                         uint16_t(systemId >> 8), uint16_t(systemId & 0xFF), 0};
  QString crcString = QString::number(CheckUtils::CheckSumOne(d), 16).rightJustified(4, '0');
  QString msg = PrefixForWriteBack + oldIDString + lengthOfControlCommand + sequenceOfControlCommand + systemIDString +
      rewriteTargetIdCommand + newIDString + systemIDString + zeroHex + crcString;
  RelayStringWriteBack(msg);

}

void TcpServer::toClearTarget(int ID)
{
  if(ID < 0){
      qDebug() << "全清指令";

      readbyteProcess->deleteRecord(-1);

      QReadLocker readLocker(&StateOfTargetMapRwLock);
      foreach(int key, StateOfTargetMap.keys())
        {
          int value = StateOfTargetMap.value(key);
          if(value > 1){
              ClearTargetHandle(key);
            }
          QThread::msleep(20);
        }
    }else{
      qDebug() << QString("清空靶标  ID  =  %1").arg(ID);
      readbyteProcess->deleteRecord(ID);
      ClearTargetHandle(ID);
    }
  emit mySignalSendInfo(api->requestClearOnly(ID));
}

void TcpServer::OpenCalibrationTarget(int ID)
{
  qDebug() << "开启靶标的校准 BLL层调用";
  QWriteLocker writeLocker(&StateOfTargetMapRwLock);
  if(!StateOfTargetMap.contains(ID)){
      qDebug() << "无法为未连接的靶标校准";
      return ;
    }
  //移除数据，防止干扰下次校准
  Container[ID].clear();

  StateOfTargetMap[ID] = CalibrationTarget;
  qDebug() << "已开启校准";
}

bool TcpServer::CloseCalibrationTarget(int ID)
{

  QWriteLocker writeLocker(&StateOfTargetMapRwLock);

    qDebug() << "关闭靶标的校准 BLL层调用";
    checkTools.SaveCalibrationData(ID);

    //更新对应ID的靶标状态
  if(!StateOfTargetMap.contains(ID)){
      qDebug() << "无法关闭未连接的靶标的校准";
      return false;
    }
  StateOfTargetMap[ID] = ToBeAssigned;
  return true;
}

//手动校准

void TcpServer::ManualCalibration(int addr, int x, int y)
{
  QString ID = QString::number(addr);

  double curLDX = TargetConfig.RakesMap[ID].LeftDownPoint.X;
  double curLDY = TargetConfig.RakesMap[ID].LeftDownPoint.Y;
  double curRUX = TargetConfig.RakesMap[ID].RightUpPoint.X;
  double curRUY = TargetConfig.RakesMap[ID].RightUpPoint.Y;
  double curSFX = TargetConfig.RakesMap[ID].ScaleFactor.X;
  double curSFY = TargetConfig.RakesMap[ID].ScaleFactor.Y;

  double meterX = 1.0 * x / (C * 1.0);
  double meterY = 1.0 * y / (C * 1.0);


   curLDX += meterX;
   curLDY += meterY;
   curRUX += meterX;
   curRUY += meterY;

   TargetConfig.RakesMap[ID].LeftDownPoint.X = curLDX;
   TargetConfig.RakesMap[ID].LeftDownPoint.Y = curLDY;
   TargetConfig.RakesMap[ID].RightUpPoint.X = curRUX;
   TargetConfig.RakesMap[ID].RightUpPoint.Y = curRUY;
   TargetConfig.RakesMap[ID].ScaleFactor.X = curSFX;
   TargetConfig.RakesMap[ID].ScaleFactor.Y = curSFY;

   //写入文件
   bool ret1 = initConfig.setArgXY(ID,"left-down-point",curLDX,curLDY);
   bool ret2 = initConfig.setArgXY(ID,"right-up-point",curRUX,curRUY);
   bool ret3 = initConfig.setArgXY(ID,"scale-factor",curSFX,curSFY);

   if(ret1 && ret2 && ret3){
       qDebug() << "二次校准成功";
     }else{
       qDebug() << "写入配置文件失败！";
     }
}

void TcpServer::ClearTargetHandle(int ID)
{
  qDebug() << "清除靶标";
  int addr = ID | 0x80;
  QString addrString = QString::number(addr, 16);
  unsigned int systemId = SystemID;
  QString systemIDString = QString::number(systemId, 16).rightJustified(4, '0');
  QVector<uint16_t> d = {0, uint16_t(systemId >> 8), uint16_t(systemId & 0xFF), 0xFE, 0, 0, 0, 0};
  QString crcString = QString::number(CheckUtils::CheckSumOne(d), 16).rightJustified(4, '0');
  QString msg = PrefixForWriteBack + addrString + lengthOfControlCommand + zeroHex +
      systemIDString + clearTargetCommand + zeroHex + zeroHex + zeroHex + zeroHex + crcString;
  RelayStringWriteBack(msg);
}

